﻿package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.filters.BevelFilter
	import flash.display.Sprite;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	 * ...
	 * @author Peter Tolstrup
	 */
	public final class Main extends Sprite 
	{
		private static const WIDTH:Number = 500;
		private static const HEIGHT:Number =380;
		
		[Embed(source = '../lib/FlowFieldAssets.swf', symbol = 'Logo')]
		private var tmp:Class;
		private var _logoGraphics:Sprite = new tmp();
		
		private var _drawShape:Shape;
		
		private var _drawBitmapData:BitmapData;
		private var _drawBitmap:Bitmap;
		
		private var _directionBitmapData:BitmapData;
		private var _directionBitmap:Bitmap;
		private var _directionOffset:Array;
		private var _directionOffsetSpeed1:Number;
		private var _directionOffsetSpeed2:Number;
		
		private var _forceBitmapData:BitmapData;
		private var _forceOffset:Array;
		private var _forceOffsetSpeed1:Number;
		private var _forceOffsetSpeed2:Number;
		
		private var stepSize:Number = 20;
		private var stepWidth:int = WIDTH / stepSize;
		private var stepHeight:int = HEIGHT / stepSize;
		
		private var radians:Number;
		private var radius:Number;
		private var xcoordinate:Number;
		private var ycoordinate:Number;					
		private var i:int = 0;
		private var j:int = 0;
		
		private static const rect:Rectangle = new Rectangle(0, 0, WIDTH, HEIGHT);
		private static const colorTransform1:ColorTransform = new ColorTransform(1, 1, 1, 0.5);
		private static const colorTransform2:ColorTransform = new ColorTransform(1, 1, 1, 0.9);		
		
		private static const MAXPARTICLES:int = 2000;

		private var particles:Array = new Array;
		private var particlesContainer:Sprite;
		private var _particleMaxSpeed:Number = 10;
		
		public function Main():void 
		{
			//stage.quality = StageQuality.MEDIUM;
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			_drawShape = new Shape();
			
			_drawBitmapData = new BitmapData(WIDTH, HEIGHT);
			_drawBitmap = new Bitmap(_drawBitmapData);
			this.addChild(_drawBitmap);
			
			_directionBitmapData = new BitmapData(stepWidth, stepHeight);
			_directionBitmap = new Bitmap(_directionBitmapData);
			_directionBitmap.width = WIDTH;
			_directionBitmap.height = HEIGHT;
			_directionOffset = [new Point(), new Point()];
			_directionOffsetSpeed1 = 0.02;
			_directionOffsetSpeed2 = -0.02;
						
			_forceBitmapData = new BitmapData(stepWidth,stepHeight);				
			_forceOffset = [new Point(), new Point()];
			_forceOffsetSpeed1 = 0.1;
			_forceOffsetSpeed2 = -0.1;
			
			particlesContainer = new Sprite();
			this.addChild(particlesContainer);
			
			var p:Particle;
			
			for ( var i:int = 0; i < MAXPARTICLES; i++)
			{
				p = new Particle();
				particlesContainer.addChild (p); 
				particles.push(p);
			}
			
			this.addChild(_logoGraphics);
			_logoGraphics.x = 10;
			_logoGraphics.y = 5;
			
			addEventListener(Event.ENTER_FRAME, update);
		}		
		
		private function update(e:Event):void 
		{
			
			_drawBitmapData.colorTransform( rect, colorTransform1 );
			
			_directionOffset[0].x += _directionOffsetSpeed1;
			_directionOffset[0].y += _directionOffsetSpeed1;			
			_directionOffset[1].x += _directionOffsetSpeed2;
			_directionOffset[1].y += _directionOffsetSpeed2;			
			_directionBitmapData.perlinNoise(stepWidth, stepHeight, 3, 1, false, false, 1, true, _directionOffset);		
			
			_forceOffset[0].x += _forceOffsetSpeed1;
			_forceOffset[0].y += _forceOffsetSpeed1;			
			_forceOffset[1].x += _forceOffsetSpeed2;
			_forceOffset[1].y += _forceOffsetSpeed2;			
			_forceBitmapData.perlinNoise(stepWidth, stepHeight, 5, 2, false, false, 1, true, _forceOffset);	
			
			
			_drawShape.graphics.clear();
			_drawShape.graphics.lineStyle(0.3, 0xcccccc);
			i = 0;
			var a:int = 0;
			var b:int = 0;
			for (i ; i < WIDTH; i += stepSize )
			{
				j = 0;
				b = 0;
				for (j; j < HEIGHT; j += stepSize )
				{	
					radians = _directionBitmapData.getPixel(a, b) / Number(0xffffff) * Math.PI * 2;
					radius = _forceBitmapData.getPixel(a, b) / 0xffffff * stepSize * 2;
					xcoordinate = radius * Math.cos(radians);
					ycoordinate = radius * Math.sin(radians);
					
					_drawShape.graphics.moveTo(i , j );
					_drawShape.graphics.lineTo(i  + xcoordinate, j + ycoordinate);
					b++;
				}
				a++;
			}
			
			
			var p:Particle;
			
			for each (p in particles) 
			{
				radians = _directionBitmapData.getPixel(p.x / stepSize, p.y / stepSize) / Number(0xffffff) * Math.PI * 2;
				radius = _forceBitmapData.getPixel(p.x / stepSize, p.y / stepSize) / 0xffffff * _particleMaxSpeed;
				xcoordinate = radius * Math.cos(radians);
				ycoordinate = radius * Math.sin(radians);
				
				p.move(xcoordinate, ycoordinate);
				
			}
	
			_drawBitmapData.draw(_drawShape, null, colorTransform2);
			_drawBitmapData.draw(particlesContainer, null);
		}	
	}	
}